òɾۿûѧϰʹá
ԭַhttps://www.joinquant.com/post/14986

ԭһ˵ʽ鵽ԭĺ߽ۡ


ԭĲԴ£

# 뺯
from jqdata import *
from datetime import datetime, timedelta
# ʼ趨׼ȵ
def initialize(context):
    # 趨300Ϊ׼
    set_benchmark('000300.XSHG')
    # ̬Ȩģʽ(ʵ۸)
    set_option('use_real_price', True)
    # ݵ־ log.info()
    log.info('ʼʼȫֻһ')
    # ˵orderϵAPIıerror͵log
    # log.set_level('order', 'error')
    
    ### Ʊ趨 ###
    # ƱÿʽʱǣʱӶ֮ʱӶ֮ǧ֮һӡ˰, ÿʽӶͿ5Ǯ
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    g.security = []
    g.counter_open = 0
    run_monthly(market_open, 8, time='open', reference_security='000300.XSHG')


# # ÿ꿪ȥѡЩƱ
def market_open(context):
    g.counter_open += 1
    if g.counter_open == 1:  
        log.info("ǰ꣬ˡcounter: " + str(g.counter_open))
        sell_all()
        date = str(context.current_dt.date())
        yesterday = (datetime.strptime(date, "%Y-%m-%d").date() - timedelta(1)).strftime("%Y-%m-%d")
        # ȡ PE, PB ҪĹƱ
        stock_list = get_stock_list(yesterday)
        # չƱƱ
        stock_list = stock_list.sort(["code"], ascending=[True])
        # ȡӦĹϢ
        # log.info("Ʊ\n" + str(stock_list))
        if stock_list.shape[0] > 0:
            stock_list["dividend_ratio"] = stock_list.apply(lambda x: DividendRatio([x[0]], yesterday), axis=1)
            stock_list = stock_list.dropna()
            stock_list = stock_list[stock_list["dividend_ratio"] > 0.03]
            # ȡ stock_list йƱҵ벢Һϲ
            industry_df = finance.run_query(
                    query(
                        finance.STK_COMPANY_INFO.code,
                        finance.STK_COMPANY_INFO.industry_id
                    ).filter(
                        finance.STK_COMPANY_INFO.code.in_(stock_list["code"].tolist())
                    )
                )
            stock_list["industry_id"] = industry_df["industry_id"].tolist()
            # PE Ϊ
            stock_list = stock_list.sort(["pe_ratio", "pb_ratio", "dividend_ratio"], ascending=[True, True, False])
            # ϢΪ
            # stock_list = stock_list.sort(["dividend_ratio", "pe_ratio", "pb_ratio"], ascending=[False, True, True])
            # ȡƱͶӦϢ
            stock_list_info, stock_list = get_stocks(stock_list, 10)
            for stock in stock_list:
                log.info('ʱ(before_market_open)' + str(context.current_dt.time()) + 'ѡƱ' + stock)
            if len(stock_list) > 6:
                g.security = stock_list
            else:
                g.security = []
            cash = context.portfolio.available_cash
            log.info("ʱ䣺" + str(context.current_dt.date()) + " " + "cash: " + str(cash))
            buy_stock(g.security, cash)
        else:
            log.info("δҵ PE, PB ҪĹƱֱӷ")
            return
    else:
        log.info("ǰڣcounter: " + str(g.counter_open))
        if g.counter_open == 6:
            g.counter_open = 0
 


# ȡ 0 < PE < 10, 0 < PB < 1.5 ĹƱ
def get_stock_list(date):
    log.info('ǰڣ' + date + 'ȡ PEPB ҪĹƱ')
    q = query(
        valuation.code,
        valuation.pe_ratio,
        valuation.pb_ratio
    )
    stock_list = get_fundamentals(q, date)
    # ˵ҪĹƱ
    stock_list = stock_list[stock_list["pe_ratio"] > 0]
    stock_list = stock_list[stock_list["pe_ratio"] < 10]
    stock_list = stock_list[stock_list["pb_ratio"] > 0]
    stock_list = stock_list[stock_list["pb_ratio"] < 1.5]
    
    return stock_list
    
# ȡӦƱ list µĹϢ
def DividendRatio(security_list,end_date,count=1):
    '''ѯϢ(ո)
    :Ʊ,ֹ,ȡ
    :panelṹ,λ:1'''
    trade_days = get_trade_days(end_date=end_date,count = count)
    security_list.sort()
    secu_list = [x[:6] for x in security_list]
    code_df = jy.run_query(query(
         jy.SecuMain.InnerCode,jy.SecuMain.SecuCode,
    #     jy.SecuMain.ChiName,jy.SecuMain.CompanyCode
        ).filter(
        jy.SecuMain.SecuCode.in_(secu_list),jy.SecuMain.SecuCategory==1).order_by(jy.SecuMain.SecuCode))
    code_df['code'] = security_list
    df = jy.run_query(query(
#         jy.LC_DIndicesForValuation    #õ
        jy.LC_DIndicesForValuation.InnerCode,
                jy.LC_DIndicesForValuation.TradingDay,
                 jy.LC_DIndicesForValuation.DividendRatio,
                ).filter(jy.LC_DIndicesForValuation.InnerCode.in_(code_df.InnerCode),
                        jy.LC_DIndicesForValuation.TradingDay.in_(trade_days)
                        ))
    f_df = df.merge(code_df,on='InnerCode').set_index(['TradingDay','code']).drop(['InnerCode','SecuCode'],axis=1)
    panel = f_df.to_panel()
    return panel.major_xs(panel.major_axis[0])["DividendRatio"].tolist()[0] if len(panel.major_axis) > 0 else None

# ȡƱҵ
def get_industry_id(code):
    df = finance.run_query(
        query(
            finance.STK_COMPANY_INFO.industry_id
        ).filter(
            finance.STK_COMPANY_INFO.code == code
        )
    )
    
    return df["industry_id"][0]

# ڱѡƱѡ 10 ֻƱעͬҵռȲܳ 10%
def get_stocks(sorted_stock_list, max_stock):
    stock_list_info = []
    stock_list = []
    occur_dict = {}
    for loc in range(sorted_stock_list.shape[0]):
        field = get_industry_id(sorted_stock_list.iloc[loc]["code"])
        if field in occur_dict:
            if occur_dict[field] >= max_stock * 0.3:
                continue
            else:
                occur_dict[field] += 1
                stock_list_info.append(sorted_stock_list.iloc[loc])
                stock_list.append(sorted_stock_list.iloc[loc]["code"])
        else:
            stock_list_info.append(sorted_stock_list.iloc[loc])
            stock_list.append(sorted_stock_list.iloc[loc]["code"])
            occur_dict[field] = 1
        if len(stock_list) >= max_stock:
            break
    return stock_list_info, stock_list

def sell_all():
    log.info("Ʊ" + str(len(g.security)))
    for stock in g.security:
        # ЩƱ
        log.info("" + stock)

        order_target(stock, 0)

def buy_stock(stock_list, sum_price):
    if stock_list is None or len(stock_list) == 0:
        log.info("δѡʹƱڿղ")
        return 
    # ȡ stock_list йƱĵռ۸
    price_dict = history(1, unit='1d', field='avg', security_list=stock_list, df=False, skip_paused=False, fq='pre')
    for stock in price_dict.keys():
        price_dict[stock] = price_dict[stock][0]
    #  sum_price ƽ䵽ЩƱ
    sum_price_dict = {}
    per_price = sum_price / len(price_dict)
    for stock in price_dict.keys():
        num = math.floor(per_price / price_dict[stock] / 100)
        log.info("룺" + stock + ", " + str(num * 100) + "")
        order(stock, num * 100)
    #     sum_price_dict[stock] = math.floor(per_price / price_dict[stock] / 100)
    # sum_value = 0
    # for stock in sum_price_dict.keys():
    #     sum_value += sum_price_dict[stock] * price_dict[stock]*100
    # res_value = sum_price - sum_value
    # return price_dict, sum_price_dict, res_value
    

